﻿// owner 蒋家伟

#include "JsonUtils.h"

// jsdk
#include "Dbg_Warn_Define.h"

namespace
{
    static const std::string base64_chars =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";

    static inline bool is_base64(const char c)
    {
        return (isalnum(c) || (c == '+') || (c == '/'));
    }
}

std::string jsdk::JsonUtils::base64_Encode(const char * bytes_to_encode, unsigned int in_len)
{
    std::string ret;

    int i = 0;
    int j = 0;

    unsigned char char_array_3[3];
    unsigned char char_array_4[4];

    while (in_len--)
    {
        char_array_3[i++] = *(bytes_to_encode++);

        if (i == 3)
        {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; (i < 4); i++)
            {
                ret += base64_chars[char_array_4[i]];
            }
            i = 0;
        }
    }

    if (i)
    {
        for (j = i; j < 3; j++)
        {
            char_array_3[j] = '\0';
        }

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (j = 0; (j < i + 1); j++)
        {
            ret += base64_chars[char_array_4[j]];
        }
        while ((i++ < 3))
        {
            ret += '=';
        }
    }
    return ret;
}

std::string jsdk::JsonUtils::base64_Decode(const char* pEncodedstring, unsigned int length)
{
    int64_t in_len = length;
    int i = 0;
    int j = 0;
    int in_ = 0;
    unsigned char char_array_4[4], char_array_3[3];
    std::string ret;

    while (in_len-- && (pEncodedstring[in_] != '=') && is_base64(pEncodedstring[in_])) {
        char_array_4[i++] = pEncodedstring[in_]; in_++;
        if (i == 4) {
            for (i = 0; i < 4; i++)
                char_array_4[i] = static_cast<unsigned char>(base64_chars.find(char_array_4[i]));

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (i = 0; (i < 3); i++)
                ret += char_array_3[i];
            i = 0;
        }
    }

    if (i) {
        for (j = i; j < 4; j++)
            char_array_4[j] = 0;

        for (j = 0; j < 4; j++)
            char_array_4[j] = static_cast<unsigned char>(base64_chars.find(char_array_4[j]));

        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
        for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
    }
    return ret;
}

void jsdk::JsonUtils::replace(JsonDocument& jsonDoc, JsonObject& jsonObject, const char* key, JsonValue&& value)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(jsonObject.IsObject(), L"Json对象不是Object对象", L"蒋家伟", L"2023-12-14");
    auto iter = jsonObject.FindMember(key);
    if (iter == jsonObject.MemberEnd())
    {
        JsonValue keyValue;
        keyValue.SetString(key, jsonDoc.GetAllocator());
        jsonObject.AddMember(keyValue, std::move(value), jsonDoc.GetAllocator());
    }
    else
    {
        iter->value.Swap(value);
    }
}

void jsdk::JsonUtils::replace(JsonDocument& jsonDoc, JsonObject& jsonObject, JsonValue&& key, JsonValue&& value)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(jsonObject.IsObject(), L"Json对象不是Object对象", L"蒋家伟", L"2023-12-14");
    auto iter = jsonObject.FindMember(key);
    if (iter == jsonObject.MemberEnd())
    {
        jsonObject.AddMember(std::move(key), std::move(value), jsonDoc.GetAllocator());
    }
    else
    {
        iter->value.Swap(value);
    }
}

jsdk::JsonObject jsdk::JsonUtils::createObject()
{
    JsonValue value;
    value.SetObject();
    return std::move(value);
}

jsdk::JsonArray jsdk::JsonUtils::createArray()
{
    JsonValue value;
    value.SetArray();
    return std::move(value);
}

void jsdk::JsonUtils::insert(JsonDocument& jsonDoc, JsonObject& jsonObject, const char* key, JsonValue&& value)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(jsonObject.IsObject(), L"Json对象不是Object对象", L"蒋家伟", L"2023-12-14");
    JsonValue keyValue;
    keyValue.SetString(key, jsonDoc.GetAllocator());
    jsonObject.AddMember(keyValue, std::move(value), jsonDoc.GetAllocator());
}

void jsdk::JsonUtils::insert(JsonDocument& jsonDoc, JsonObject& jsonObject, JsonValue&& key, JsonValue&& value)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(jsonObject.IsObject(), L"Json对象不是Object对象", L"蒋家伟", L"2023-12-14");
    jsonObject.AddMember(std::move(key), std::move(value), jsonDoc.GetAllocator());
}

const jsdk::JsonValue* jsdk::JsonUtils::getJsonValue(const JsonObject& jsonObject, const char* key)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(jsonObject.IsObject(), L"Json对象不是Object对象", L"蒋家伟", L"2023-12-14");
    auto memberIter = jsonObject.FindMember(key);
    if (memberIter != jsonObject.MemberEnd())
    {
        return &(memberIter->value);
    }

    return nullptr;
}

bool jsdk::JsonUtils::hasMember(const JsonObject& jsonObject, const char* key)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(jsonObject.IsObject(), L"Json对象不是Object对象", L"蒋家伟", L"2023-12-14");
    return jsonObject.FindMember(key) != jsonObject.MemberEnd();
}

jsdk::JsonValue jsdk::JsonUtils::getDataStream(const std::string& value, JsonDocument& jsonDoc)
{
    uint64_t size = value.size() * sizeof(char);
    return JsonUtils::getDataStreamImp((void*)(value.c_str()), size, jsonDoc);
}

jsdk::JsonValue jsdk::JsonUtils::getDataStream(const std::wstring& value, JsonDocument& jsonDoc)
{
    uint64_t size = value.size() * sizeof(wchar_t);
    return JsonUtils::getDataStreamImp((void*)(value.c_str()), size, jsonDoc);
}

jsdk::JsonValue jsdk::JsonUtils::getDataStreamImp(const void* pSource, const uint64_t& size, JsonDocument& jsonDoc)
{
    std::vector<char> array(size);
    std::memcpy(array.data(), pSource, size);
    const std::string& base64Str = JsonUtils::base64_Encode(array.data(), static_cast<uint32_t>(size));
    return JsonValue(base64Str.c_str(), static_cast<rapidjson::SizeType>(base64Str.size()), jsonDoc.GetAllocator());
}

bool jsdk::JsonUtils::getValueFromJsonValue(const jsdk::JsonValue& value, std::wstring& wstr)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(value.IsString(), L"存储的对象不是字节流", L"蒋家伟", L"2023-12-14");
    const std::string& sourceStr = JsonUtils::base64_Decode(value.GetString(), value.GetStringLength());
    wstr.resize(sourceStr.size() / sizeof(wchar_t));
    std::memcpy((void*)wstr.c_str(), sourceStr.c_str(), sourceStr.size());
    return true;
}

bool jsdk::JsonUtils::getValueFromJsonValue(const JsonValue* pValue, std::string& str)
{
    if (pValue)
        return getValueFromJsonValue(*pValue, str);
    return false;
}

bool jsdk::JsonUtils::getValueFromJsonValue(const JsonValue* pValue, std::wstring& wstr)
{
    if (pValue)
        return getValueFromJsonValue(*pValue, wstr);
    return false;
}

bool jsdk::JsonUtils::getValueFromJsonValue(const jsdk::JsonValue& value, std::string& str)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(value.IsString(), L"存储的对象不是字节流", L"蒋家伟", L"2023-12-14");
    const std::string& sourceStr = JsonUtils::base64_Decode(value.GetString(), value.GetStringLength());
    str.resize(sourceStr.size() / sizeof(char));
    std::memcpy((void*)str.c_str(), sourceStr.c_str(), sourceStr.size());
    return true;
}

bool jsdk::JsonUtils::getValueFromJsonValueImp(const jsdk::JsonValue& value, const uint64_t& size, void* pDest)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(value.IsString(), L"存储的对象不是字节流", L"蒋家伟", L"2023-12-14");
    const std::string& sourceStr = JsonUtils::base64_Decode(value.GetString(), value.GetStringLength());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(sourceStr.size() == size, L"存储的数据与传入类型字节流数量不匹配", L"蒋家伟", L"2023-12-01");
    std::memcpy(pDest, sourceStr.c_str(), sourceStr.size());
    return true;
}

bool jsdk::JsonUtils::getValueFromJsonValueImp(const JsonValue* pValue, const uint64_t& size, void* pDest)
{
    if (pValue)
        return getValueFromJsonValueImp(*pValue, size, pDest);
    return false;
}
